package com.estock.platform.manager;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.estock.common.model.security.Stock;
import com.estock.common.model.task.Task;
import com.estock.common.util.CommonUtil;
import com.estock.common.util.DateUtil;
import com.estock.platform.task.support.TaskThreadRepository;

@Component
public class CacheManager {
	
	private static Logger logger = Logger.getLogger(CacheManager.class); 
	
	private static CacheManager instance;
	
	private Set<Stock> stocks = new HashSet<Stock>();
	private Set<Task> tasks = new HashSet<Task>();
	
	@PostConstruct
	public static CacheManager getInstance() {
		if (instance == null) {
			instance = new CacheManager();
			instance.init();
		}
		return instance;
	}
	
	public void init() {
		loadStocks();
		loadTasks();
	}

	public Set<Stock> getStocks() {
		return stocks;
	}
	
	public List<Stock> getStocksShldUpdateTrans() {
		List<Stock> results = new ArrayList<Stock>();
		Date now = new Date();
		for (Stock stock: stocks) {
			// check if there aleady has stocks under temp dir, do not request for the existing file.
			String filepath = CommonUtil.getYahooCsvDataDir() + stock.getCode() + ".csv";
			if (new File(filepath).exists()) {
				continue;
			}
					
			Date lastTransDay = stock.getStockPrice().getLastTransDay();
			// one stock one day, can only download onetime.
			if (lastTransDay == null || DateUtil.dayBefore(lastTransDay, DateUtils.addDays(now, -1))) {
				results.add(stock);
			}
		}
		
		logger.info("Total stocks whose trans should be updated: " + results.size());
		if (CommonUtil.isUnitTest) {
			System.out.println("Total stocks whose trans should be updated: " + results.size());
		}
		return results;
	}

	public void refreshWithStock(Stock savedStock) {
		for (Stock stock : stocks) {
			if (stock.equals(savedStock)) {
				stock = savedStock;
				return;
			}
		}
		this.stocks.add(savedStock);
	}

	public Set<Task> getTasks() {
		return tasks;
	}
	
	public void refreshWithSavedTask(Task savedTask) {
		for (Task task : tasks) {
			if (task.equals(savedTask)) {
				task = savedTask;
				return;
			}
		}
		this.tasks.add(savedTask);
		TaskThreadRepository.getInstance().register(savedTask);
	}
	
	public void loadStocks() {
		try {
			List<Stock> stocks = DBManager.getInstance().findAllStocks();
			logger.info("get stock list from local server, with size of " + stocks.size());
			System.out.println("get stock list from local server, with size of " + stocks.size());
			
			this.stocks.addAll(stocks);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void loadTasks() {
		try {
			List<Task> tasks = DBManager.getInstance().findAllTasks();
			logger.info("get task list from local server, with size of " + tasks.size());
			System.out.println("get task list from local server, with size of " + tasks.size());
			
			this.tasks.addAll(tasks);
			//TaskThreadRepository.getInstance().register(this.tasks);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
